Skip to content

WIP: add rv renv lock generation#430

Open
dpastoor wants to merge 3 commits intomainfrom
renv-lock
Open

WIP: add rv renv lock generation#430
dpastoor wants to merge 3 commits intomainfrom
renv-lock

Conversation

@dpastoor
Copy link
Copy Markdown
Member

@dpastoor dpastoor commented Mar 23, 2026

currently all AI generated, but tracking here - the core need is to be better able to properly generate a renv.lock file suitable for other tooling that needs that off of an rproject.toml/rv.lock.

  • e2e will need to be completely deleted/actually re-written

Summary

This PR adds an rv renv lock workflow so an rv project can emit a renv-compatible renv.lock for downstream tooling that expects the renv format.

The generator uses rv.lock as the source of truth for resolved package sources and dependency relationships, then enriches that data with installed DESCRIPTION metadata from the synced library so the output looks like a real renv lockfile instead of a lossy export.

The branch also adds:

  • repository alias handling so the generated Repository field comes from rproject.toml rather than server-stamped DESCRIPTION values like RSPM
  • package exclusion support for trimming dev-only top-level packages from the generated renv.lock
  • a --dry-run report for reviewing what an exclusion set would remove
  • CLI tests and e2e comparison fixtures against a native renv::snapshot() baseline

The goal here is interoperability, not to make renv the source of truth.

rv.lock already knows which packages were resolved and where they came from, but it does not carry all of the package metadata that renv writes into renv.lock entries. To produce something renv-compatible, this implementation reads the installed library's DESCRIPTION files and merges those fields with source metadata from rv.lock.

That design gives us:

  • rv remains the canonical project manager and lockfile format
  • renv.lock becomes an export artifact that can be generated on demand
  • the generated lockfile includes the fields renv-based consumers expect, such as package metadata, dependency arrays, and remote metadata

In particular, the git metadata fields are required for other tools restoring packages that come from git. As rv does not inject that into the description, without that making it into the renv.lock, other tools cannot restore packages from git the same way they come into rv

Design Notes

Lockfile generation

  • Adds a new rv renv lock subcommand.
  • Requires an up-to-date rv.lock and a synced library, because the generator reads DESCRIPTION files from the installed library path.
  • Omits builtin/base packages from the generated output.

How package metadata is built

  • rv.lock provides source information and dependency structure.
  • Installed DESCRIPTION files provide package metadata such as Title, Authors@R, Depends, Suggests, and similar renv-visible fields.
  • Dependency-like DESCRIPTION fields are converted into renv-style JSON arrays.

Source mapping

  • Repository packages become Source = "Repository" and use the repository alias from rproject.toml.
  • Git packages are currently mapped only for GitHub remotes, producing renv Remote* metadata from the resolved git source.
  • RUniverse packages are exported as repository packages with extra remote provenance fields.
  • Local packages are exported as Source = "Local".
  • URL sources and non-GitHub git remotes are rejected for now because there is not a clean renv-compatible mapping implemented yet.

Repository field override

One of the explicit fixes in this branch is that generated repository entries should not leak server-stamped Repository values from DESCRIPTION files.

For example, a package installed from Posit Package Manager may carry Repository: RSPM in DESCRIPTION, but the generated renv.lock should use the configured alias from rproject.toml, such as CRAN. The same logic applies to custom/internal repositories.

Excluding packages from the export

The tip commit adds --exclude-pkgs and --dry-run for cases where we want a slimmer exported renv.lock, especially around dev-only top-level packages.

The exclusion design is intentionally conservative:

  • only top-level dependencies from rproject.toml can be excluded
  • transitive dependencies are removed only if they are needed exclusively by excluded packages
  • shared dependencies are retained
  • --dry-run reports direct exclusions, transitive removals, and retained shared dependencies without writing a file

commands

Write to an explicit path:

rv renv lock --output renv.lock

Generate a reduced export that omits dev-only top-level packages where possible:

rv renv lock --exclude-pkgs devtools,linter

Preview the exclusion impact without writing renv.lock:

rv renv lock --exclude-pkgs devtools --dry-run

Machine-readable dry-run output:

rv renv lock --exclude-pkgs devtools --dry-run --json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant